/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "driver/uart.h"
#include "driver/gpio.h"

#include "esp_event.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "esp_log.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>


#include "dirent.h"
#include "esp_vfs.h"
#include "esp_spiffs.h"
#include "ff.h"
#include "nvs.h"
#include "nvs_flash.h"

static const char *TAG = "example";


static ip4_addr_t s_ip_addr;

static int isConnect=0;

static void wifi_state_handler(void *arg, esp_event_base_t event_base,
                               int32_t event_id, void *event_data)
{
  char*p=(char*)arg;
  printf("########wifi_state_handler %d\r\n",*p);
  if(*p==1){
      //连接失败
      printf("########on_wifi_disconnect\r\n");
      system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data;

      ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
      if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) {
          /*Switch to 802.11 bgn mode */
          esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N);
      }
      esp_wifi_connect();
  }else if(*p==2){
    //连接上wifi
    printf("########on_wifi_connect %d\r\n",*p);
    ESP_LOGI(TAG, "Wi-Fi connected ");
  }else if(*p==3){
    //获取到ip地址
    ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
    memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr));

    u32_t  ip=s_ip_addr.addr;
    //printf("########on_got_ip\r\n");
    //printf("ip:%d.%d.%d.%d\r\n",(ip)&0x0FF,(ip>>8)&0x0FF,(ip>>16)&0x0FF,(ip>>24)&0x0FF);


    tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_AP;
    tcpip_adapter_ip_info_t ip_info;
    tcpip_adapter_get_ip_info(tcpip_if,&ip_info);
    ip=ip_info.ip.addr;
    printf("AP-ip:%d.%d.%d.%d\r\n",(ip)&0x0FF,(ip>>8)&0x0FF,(ip>>16)&0x0FF,(ip>>24)&0x0FF);


    tcpip_if = TCPIP_ADAPTER_IF_STA;
    tcpip_adapter_get_ip_info(tcpip_if,&ip_info);
    ip=ip_info.ip.addr;
    printf("ip:%d.%d.%d.%d\r\n",(ip)&0x0FF,(ip>>8)&0x0FF,(ip>>16)&0x0FF,(ip>>24)&0x0FF);
    isConnect=1;
  }
   
}




static char ssid[32] ="biaodiankeji";
static char password[32] ="bdkj6666";
static char p[]={1,2,3};
void connectWifi(){


    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &wifi_state_handler, &p[0]);
    esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &wifi_state_handler, &p[1]);
    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_state_handler, &p[2]);

    
    esp_wifi_set_storage(WIFI_STORAGE_RAM);
    wifi_config_t wifi_config = { 0 };

    strncpy((char *)&wifi_config.sta.ssid, ssid, 32);
    strncpy((char *)&wifi_config.sta.password, password, 32);

    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
    esp_wifi_start();
    esp_wifi_connect();
}

#define PORT 23
static void socketTask(void *pvParameter){
    //等待连接网络
    while(1){
        if(isConnect==1){
            break;
        }
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }

    printf("----create socket\r\n");
    int addr_family=AF_INET;
    int ip_protocol=IPPROTO_IP;
    char rx_buffer[128];
    char addr_str[128];

    struct sockaddr_in destAddr;
    destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    destAddr.sin_family = AF_INET;
    destAddr.sin_port = htons(PORT);
    inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);


     int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
    if (listen_sock < 0) {
        ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
    }
    ESP_LOGI(TAG, "Socket created");

    int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
    if (err != 0) {
        ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
    }
    ESP_LOGI(TAG, "Socket binded");

    err = listen(listen_sock, 1);
    if (err != 0) {
        ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
    }
    ESP_LOGI(TAG, "Socket listening");
    struct sockaddr_in sourceAddr;
    uint addrLen = sizeof(sourceAddr);
    int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
    if (sock < 0) {
        ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
    }
    ESP_LOGI(TAG, "Socket accepted");
    sprintf(rx_buffer,"%s","wecome esp32\r\n username:");
    send(sock, rx_buffer, strlen(rx_buffer), 0);
    while(1){
            int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
            // Error occured during receiving
            if (len < 0) {
                ESP_LOGE(TAG, "recv failed: errno %d", errno);
                break;
            }else if (len == 0) {
                ESP_LOGI(TAG, "Connection closed");
                break;
            }else{
                rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
                //ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
                //printf("--------------%d--------------\r\n",len);
               // ESP_LOGI(TAG, "%s", rx_buffer);
               printf("%s",rx_buffer);
               //printf("[[[%d]]]",len);
            }
    }

    vTaskDelete(NULL);
}



void app_main()
{
    uart_set_baudrate(UART_NUM_0,74880);
    
    printf("Hello world!\n");
    connectWifi();
    xTaskCreate(socketTask, "socketTask", 2048, NULL, 1, NULL);
    // char InfoBuffer[200];
    // vTaskList(InfoBuffer);
    // printf("taskName\ttaskState\ttaskPrio\ttaskStack\ttaskNum\r\n");
    // printf("%s",InfoBuffer);
}
